package com.tom.architect.day04;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.tom.architect.R;
import com.tom.architect.day02.MainActivity2;

import org.w3c.dom.Text;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class MainActivity4 extends BaseActivity {

    @ViewById(R.id.tv) // 注解注入。
    private TextView tv;

    @ViewById(R.id.tv1) // 注解注入。
    private TextView tv1;
    private int mPage;

//    private <T,P> T viewById(P viewId)
    // 方法泛型
    private <T extends View> T viewById(int viewId) {
        return (T) findViewById(viewId);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
//        zhuJie();
//        fanXing01();

//        startActivity1(MainActivity4.class);
    }

    // 类的泛型。
    private void fanXing01() {
        MyArrayList<String> arrayList = new MyArrayList();
        // arrayList.add(1);
        arrayList.add("1");

        HttpCallBack callBack = new HttpCallBack<BaseResult>() {
            @Override
            public void onSuccess(BaseResult result) { // 类泛型的使用。与上面类型一致。

            }
        };
    }

    // 注解
    private void zhuJie() {
        ViewUtils.inject(this); // 注入，代码不能少。

        tv.setText("welcome! 1607");
        tv1.setText("wakaka");
    }


    // 反射的使用。
    private void fanShe() {
        // 访问hide的构造函数，通过反射。
        // AssetManager assetManager = new AssetManager();
        // Resources res = new Resources(assetManager, null, null);
//        ActivityThread /Class

        // TestBean testBean = new TestBean();
        try {
            // 创建对象，很多系统的类，都被系统隐藏了。或者说只有系统可以直接new，可以通过反射来创建对象。
            // newInstance() 调用的是无参的构造函数。ava.lang.Class<com.tom.architect.day04.TestBean> has no zero argument constructor
            /* TestBean testBean = TestBean.class.newInstance(); // new对象
            testBean.sysName(); */

            // 反射的使用。getDeclaredConstructor 从所有的构造方法中找。getConstructor 从公共构造方法中找。
            // 获取一个参数的构造方法，且参数是String类型。int.class
            Constructor constructor = TestBean.class.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);
            // "XiaoLi"调用构造方法，传的参数 === new TextBean("XiaoLi"), 创建对象。解决私有构造方法，隐藏构造方法。
            TestBean testBean = (TestBean) constructor.newInstance("XiaoLi");
            testBean.sysName();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 2.方法调用
        try {
//            TestBean testBean = new TestBean("Zhuzu"); // 对象
//            // 方法名，不要带括号。
//            Method method = TestBean.class.getDeclaredMethod("sysName");
//            method.setAccessible(true);
//            method.invoke(testBean); // 方法method，被testBean对象执行。

            AssetManager assetManager = AssetManager.class.newInstance(); // 解决不能实例化的问题。
            // addAssetPath(String path)
            // 拿到方法去调用。这个方法是系统 @hide，只能反射调用。
            Method addAssetPathMethod = AssetManager.class.getDeclaredMethod("addAssetPath", String.class);
            addAssetPathMethod.invoke(assetManager, "sdcard/dds/red.skin");
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 3.属性获取。私有的属性
        try {
            TestBean testBean = new TestBean("Dog");
            Field field = TestBean.class.getDeclaredField("name"); // 传入属性名称。
            field.setAccessible(true);
            String name = (String) field.get(testBean); // 获取属性
            Log.e("TAG", "name:" + name);

            // 插件化开发ActivityThread中获取 sCurrentActivityThread 属性。
            Class clazz = Class.forName("android.app.ActivityThread");
            Field sCurrentActivityThreadField = clazz.getDeclaredField("sCurrentActivityThread");
            sCurrentActivityThreadField.setAccessible(true);
            // 静态的，跟对象没关系，跟类没关，可以直接传null。
            // private static volatile ActivityThread sCurrentActivityThread; (ActivityThread.java L228)
            Object sCurrentActivityThread = sCurrentActivityThreadField.get(null);
            Log.e("TAG", sCurrentActivityThread.toString());
            // 在调用反射获取mH对象，然后去替换，做到 移尸还魂
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


//: java.lang.NoSuchMethodException: com.tom.architect.day04.TestBean.<init> [class java.lang.String]
// W/System.err:     at java.lang.Class.getConstructor0(Class.java:2332)
// W/System.err:     at java.lang.Class.getConstructor(Class.java:1728)
// W/System.err:     at com.tom.architect.day04.MainActivity4.onCreate(MainActivity4.java:34)
// W/System.err:     at android.app.Activity.performCreate(Activity.java:8214)
// W/System.err:     at android.app.Activity.performCreate(Activity.java:8202)
// W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320)
// W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4038)
// W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4252)
// W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
// W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
// W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
// W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2618)
// W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:110)
// W/System.err:     at android.os.Looper.loop(Looper.java:219)
// W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:8673)
// W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
// W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
// W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)